home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
bipl.zip
/
PROGS.ZIP
/
MEMSUM.ICN
< prev
next >
Wrap
Text File
|
1992-09-28
|
7KB
|
239 lines
############################################################################
#
# File: memsum.icn
#
# Subject: Program to summarize Icon memory management
#
# Author: Ralph E. Griswold
#
# Date: April 17, 1990
#
###########################################################################
#
# This program is a filter for Icon allocation history files (see IPD113).
# It tabulates the number of allocations by type and the total amount of
# storage (in bytes) by type.
#
# It takes an Icon allocation history file from standard input and writes to
# standard output.
#
# The command-line options are:
#
# -t produce tab-separated output for use in spreadsheets (the
# default is a formatted report)
#
# -d produce debugging output
#
# -g produce garbage-collection details (formatted report only)
#
# -z list types with zero allocation (the default is to not list
# them)
#
# Some assumptions are made about where newlines occur -- specifically
# that verification commands are on single lines and that refresh and
# garbage collection data are on multiple lines.
#
############################################################################
#
# Links: numbers, options
#
############################################################################
link numbers, options
global cmds, highlights, lastlen, alloccnt, alloctot, collections
global mmunits, diagnose, namemap, zeroes, gdetail
procedure main(args)
local line, region, s, skip, opts, prefix
opts := options(args,"dgtz")
diagnose := if \opts["d"] then write else 1
gdetail := if \opts["g"] then 1
display := if \opts["t"] then spread else report
zeroes := if \opts["z"] then 1
cmds := 'cefihLlRrSsTtux"XAF' # command characters
highlights := '%$Y' # highlight commands
mmunits := 4 # default; reset if different
namemap := table("*** undefined ***")
namemap["b"] := "large integer"
namemap["c"] := "cset"
namemap["e"] := "table-element tv"
namemap["f"] := "file"
namemap["h"] := "hash block"
namemap["i"] := "large integer"
namemap["L"] := "list header"
namemap["l"] := "list element"
namemap["R"] := "record"
namemap["r"] := "real number"
namemap["S"] := "set header"
namemap["s"] := "set element"
namemap["T"] := "table header"
namemap["t"] := "table element"
namemap["u"] := "substring tv"
namemap["x"] := "refresh block"
namemap["\""] := "string"
namemap["X"] := "co-expression"
namemap["A"] := "alien block"
namemap["F"] := "free space"
lastlen := table() # last size
alloccnt := table(0) # count of allocations
alloctot := table(0) # total allocation
collections := list(4,0) # garbage collection counts
every alloccnt[!cmds] := 0
every alloctot[!cmds] := 0
cmds ++:= highlights
while line := read() do # input from allocation history file
line ? {
if prefix := tab(upto('{=#;!<>')) then {
case move(1) of {
!"=#;!>": next
"{": { # refresh sequence
collections[prefix] +:= 1
while line := read() | stop("**** premature eof") do
line ? if upto('#!') then break next
}
"<": {
mmunits := integer(prefix) # covers old case with no value
while line := read() | stop("**** premature eof") do
line ? if upto('#>') then break next
}
}
}
else { # process allocation
while move(process(tab(upto(cmds) + 1)))
}
}
display()
end
# Display a table of allocation data
#
procedure report()
local name, cnt, cnttotal, i, tot, totalcoll, tottotal
static col1, col2, gutter # column widths
initial {
col1 := 16 # name field
col2 := 10 # number field
gutter := repl(" ",6)
}
write(, # write column headings
"\n",
left("type",col1),
right("number",col2),
gutter,
right("bytes",col2),
gutter,
right("average",col2),
gutter,
right("% bytes",col2),
"\n"
)
alloccnt := sort(alloccnt,3) # get the data
alloctot := sort(alloctot,3)
cnttotal := 0
tottotal := 0
every i := 2 to *alloccnt by 2 do {
cnttotal +:= alloccnt[i]
tottotal +:= alloctot[i]
}
while name := get(alloccnt) do {
if ((cnt := get(alloccnt)) = 0) & /zeroes then { # skip zero entries
get(alloctot) # remove unused values
get(alloctot)
next # get next group
}
write( # write the data
left(namemap[name],col1), # name
right(cnt,col2), # number of allocations
gutter,
get(alloctot) & right(tot := get(alloctot),col2), # space allocated
gutter,
fix(tot,cnt,col2) | repl(" ",col2),
gutter,
fix(100.0 * tot,tottotal,col2) | repl(" ",col2)
)
}
write( # write totals
"\n",
left("total:",col1),
right(cnttotal,col2),
gutter,
right(tottotal,col2),
gutter,
fix(tottotal,cnttotal,col2) | repl(" ",col2)
)
totalcoll := 0 # garbage collections
every totalcoll +:= !collections
write("\n",left("collections:",col1),right(totalcoll,col2))
if totalcoll > 0 then {
write(left(" static region:",col1),right(collections[1],col2))
write(left(" string region:",col1),right(collections[2],col2))
write(left(" block region:",col1),right(collections[3],col2))
write(left(" no region:",col1),right(collections[4],col2))
}
return
end
# Produce tab-separated output for a spreadsheet. The first column
# is the type name, the second column is the number of allocations,
# and the third column is the total number of bytes allocated for that
# type.
#
procedure spread()
local name, number, total
alloccnt := sort(alloccnt,3) # get the data
alloctot := sort(alloctot,3)
write("type\tnumber\ttotal bytes") # label row
while name := namemap[get(alloccnt)] do {
number := get(alloccnt)
get(alloctot)
total := get(alloctot)
if (number = 0) & /zeroes then next
write(name,"\t",number,"\t",total)
}
return
end
# Process data
#
procedure process(s)
local cmd, len
s ? {
tab(upto('+') + 1) # skip address
len := tab(many(&digits)) | &null
cmd := move(1)
if cmd == !highlights then return 2 else {
# if given len is nonstring, scale
if cmd ~== "\"" then \len *:= mmunits
alloccnt[cmd] +:= 1
(/len := lastlen[cmd]) | (lastlen[cmd] := len)
diagnose(&errout,"cmd=",cmd,", len=",len)
alloctot[cmd] +:= len
return 0
}
}
end